package com.hlx.herostory.cmdhandler;

import com.google.protobuf.GeneratedMessageV3;
import com.hlx.herostory.utils.PackageUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 指令处理器工厂
 */
public final class CmdHandlerFactory {

    private static final Logger log = LoggerFactory.getLogger(CmdHandlerFactory.class);

    /**
     * 处理器字典
     */
    static private Map<Class<?>, ICmdHandler<? extends GeneratedMessageV3>> _handlerMap = new HashMap<>();

    /**
     * 私有化类默认构造器
     */
    private CmdHandlerFactory() {
    }

    /**
     * 初始化
     */
    static public void init() {
        log.info("==== 完成 Cmd 和 Handler 的关联 ====");

        // 拿出所有实现ICmdHandler的子类
        Set<Class<?>> clazzes = PackageUtil.listSubClazz(
                CmdHandlerFactory.class.getPackage().getName(),
                true,
                ICmdHandler.class);

        for (Class<?> clazz : clazzes) {
            if ((clazz.getModifiers() & Modifier.ABSTRACT) != 0) {
                // 如果是抽象类,
                continue;
            }

            // 获取方法数组
            Method[] methodArray = clazz.getDeclaredMethods();

            // 消息类型
            Class<?> msgType = null;
            for (Method method : methodArray) {
                if (!method.getName().equals("handle")) {
                    // 不是handle方法
                    continue;
                }

                Class<?>[] parameterTypes = method.getParameterTypes();

                if (parameterTypes.length < 2 ||
                        parameterTypes[1] == GeneratedMessageV3.class ||
                        !GeneratedMessageV3.class.isAssignableFrom(parameterTypes[1])) {
                    continue;
                }

                msgType = parameterTypes[1];
                break;
            }

            if (null == msgType) {
                continue;
            }

            try {
                ICmdHandler<?> newHandler = (ICmdHandler<?>) clazz.newInstance();

                log.info(
                        "关联 {} <==> {}",
                        msgType.getName(),
                        clazz.getName()
                );
                _handlerMap.put(msgType, newHandler);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    /**
     * 创建指令处理器工厂
     *
     * @param msgClazz 消息类
     * @return
     */
    static public ICmdHandler<? extends GeneratedMessageV3> create(Class<?> msgClazz) {
        if (null == msgClazz) {
            return null;
        }

        return _handlerMap.get(msgClazz);
    }
}

